<template>
  <grid-layout
    :layout.sync="layout"
    :col-num="colNum"
    :row-height="rowHeight"
    :is-draggable="true"
    :is-resizable="true"
    :vertical-compact="verticalCompat"
    :margin="margin"
    :use-css-transforms="!disableCssTransforms"
  >
    <grid-item
      v-for="item in layout"
      v-bind="item"
      :key="item.i"
      class="grid-item"
    >
      <component :is="runtime.placeholder" :template="item.el" />
    </grid-item>
  </grid-layout>
</template>

<style lang="scss" scoped src="./common.scss"></style>

<script>
import Vue from 'vue';
import { GridLayout, GridItem } from 'vue-grid-layout';

export default {
  name: 'GridBox',
  inject: ['runtime'],
  components: {
    GridLayout,
    GridItem,
  },
  props: {
    colNum: {
      type: Number,
      default: 12,
    },
    rowHeight: {
      type: Number,
      default: 30,
    },
    margin: {
      type: Array,
      default() {
        return [10, 10];
      },
    },
    verticalCompat: Boolean,
    disableCssTransforms: Boolean,
  },
  computed: {
    layout: {
      set(layout) {
        this.$set(
          this.runtime.node.template,
          'elements',
          layout.map((item) => {
            const el = this.runtime.node.template.elements.find(
              (el) => el.name === item.i,
            );
            if (!el || !el.layout) {
              throw new Error(`unexpected item of name: ${item.i}`);
            }
            el.layout.x = item.x;
            el.layout.y = item.y;
            el.layout.w = item.w;
            el.layout.h = item.h;
            return el;
          }),
        );
      },
      get() {
        const $vm = this;
        return (this.runtime.node.template.elements || []).map((el) => {
          if (!el.layout) {
            $vm.$set(
              el,
              'layout',
              Vue.observable({
                x: 0,
                y: 0,
                w: 1,
                h: 1,
              }),
            );
          }
          return Vue.observable({
            ...el.layout,
            i: el.name,
            el,
          });
        });
      },
    },
  },
};
</script>
